package com.evil.account.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.evil.account.pojo.entity.Department;
import com.evil.common.account.dto.FindByNameAndEIdReqDTO;
import com.evil.common.account.dto.FindByNamesAndEIdReqDTO;
import com.evil.common.account.dto.department.DepartmentBaseRespDTO;
import com.evil.common.account.dto.department.DepartmentPageReqDTO;
import com.evil.common.account.dto.department.DepartmentPageRespDTO;
import com.evil.common.account.dto.department.DepartmentTreeReqDTO;
import com.evil.common.account.util.AccountRedisKeyUtil;
import com.evil.common.core.constant.RedisConstant;
import com.evil.common.core.entity.QueryModel;
import com.evil.common.core.enums.RCodeEnum;
import com.evil.common.core.enums.SwitchEnum;
import com.evil.common.core.exception.BusinessException;
import com.evil.common.core.util.CacheMapperUtil;
import com.evil.common.core.util.StreamUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.ibatis.annotations.Param;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 部门表
 *
 * @author liyang
 * @date 2022-08-08 00:00
 */
public interface DepartmentMapper extends BaseMapper<Department> {

    default Optional<Department> isExistById(Long id) {
        return Optional.ofNullable(this.selectById(id));
    }

    default Optional<Department> isExistById_Cache(Long id) {
        return CacheMapperUtil.cacheById(
                id,
                Department.class,
                this::findById,
                AccountRedisKeyUtil::requestUuidDepartmentKey,
                RedisConstant.REQUEST_UUID_EXPIRE_IN_SECOND
        );
    }

    default Department findById(Long id) {
        return this.isExistById(id).orElseThrow(() -> new BusinessException(RCodeEnum.USER_NOT_EXIST));
    }

    default Department findById_Cache(Long id) {
        return this.isExistById(id).orElseThrow(() -> new BusinessException(RCodeEnum.USER_NOT_EXIST));
    }

    default Department findNormalById(Long id) {
        return this.isExistById(id)
                .filter(d -> !SwitchEnum.isOpen(d.getIsDeleted()))
                .orElseThrow(() -> new BusinessException(RCodeEnum.USER_NOT_EXIST));
    }

    List<Department> findByIds(@Param("ids") Collection<Long> ids, @Param("filterDeleted") boolean filterDeleted);

    List<Department> findByEnterpriseId(@Param("enterpriseId") Long enterpriseId);

    List<Department> findByParentId(@Param("parentId") Long parentId);

    List<Department> findByTree(DepartmentTreeReqDTO departmentTreeReqDTO);

    List<Department> findByParentIds(@Param("parentIds") Collection<Long> parentIds);

    default Map<Long, Department> findMapByIds(Collection<Long> ids, boolean filterDeleted) {
        return StreamUtil.toMapK(this.findByIds(ids, filterDeleted), Department::getDepartmentId);
    }

    DepartmentBaseRespDTO findBaseById(@Param("id") Long id);

    Optional<DepartmentBaseRespDTO> isExistBaseByName(FindByNameAndEIdReqDTO findByNameAndEIdReqDTO);

    default DepartmentBaseRespDTO findBaseByName(FindByNameAndEIdReqDTO findByNameAndEIdReqDTO) {
        return this.isExistBaseByName(findByNameAndEIdReqDTO).orElseThrow(() -> new BusinessException(RCodeEnum.DEPARTMENT_NOT_EXIST));
    }

    List<DepartmentBaseRespDTO> findBaseByIds(@Param("ids") Collection<Long> ids, @Param("filterDeleted") boolean filterDeleted);

    List<DepartmentBaseRespDTO> findBaseByEnterpriseId(@Param("enterpriseId") Long enterpriseId);

    default List<DepartmentBaseRespDTO> findBaseByIds_Cache(Collection<Long> ids, boolean filterDeleted) {
        return CacheMapperUtil.cacheByIds(
                ids,
                filterDeleted,
                DepartmentBaseRespDTO.class,
                this::findBaseByIds,
                DepartmentBaseRespDTO::getDepartmentId,
                u -> SwitchEnum.NO.getId(),
                null,
                AccountRedisKeyUtil::requestUuidDepartmentBaseKeyMap,
                RedisConstant.REQUEST_UUID_EXPIRE_IN_SECOND
        );
    }

    default Map<Long, DepartmentBaseRespDTO> findBaseMapByIds(Collection<Long> ids, boolean filterDeleted) {
        return StreamUtil.toMapK(this.findBaseByIds(ids, filterDeleted), DepartmentBaseRespDTO::getDepartmentId);
    }

    List<DepartmentPageRespDTO> departments(DepartmentPageReqDTO departmentPageReqDTO);

    List<DepartmentBaseRespDTO> findBaseByNames(FindByNamesAndEIdReqDTO findByNamesAndEIdReqDTO);

    default PageInfo<DepartmentPageRespDTO> departmentPage(QueryModel<DepartmentPageReqDTO> queryModel) {
        return PageHelper.startPage(queryModel.getPageNum(), queryModel.getPageSize(), queryModel.initOrder())
                .doSelectPageInfo(() -> this.departments(queryModel.getParam()));
    }
}